"""
规范性分析服务
基于规范性分析结果进行信访答复的规范性评估和分析
"""
from typing import Dict, Any, List, Optional
from datetime import datetime
from sqlalchemy.orm import Session
from sqlalchemy import func, desc, and_, or_
import json

from .base_analyzer import BaseAnalyzer, AnalysisFilters, AnalysisResult
from models.petition_record import ComplianceAnalysisResult
from models.analysis_task import AnalysisTask
from core.logging_config import get_logger

# 日志记录器
logger = get_logger("compliance_analyzer")


class ComplianceAnalysisFilters(AnalysisFilters):
    """规范性分析过滤器"""

    def __init__(self):
        super().__init__()
        self.compliance_status: Optional[str] = None  # 合规状态: compliant, non_compliant, partial
        self.compliance_type: Optional[str] = None  # 规范性类型
        self.min_confidence: Optional[float] = None  # 最小置信度
        self.issue_category: Optional[str] = None  # 问题类别


class ComplianceAnalyzer(BaseAnalyzer):
    """规范性分析器"""

    def get_model_class(self):
        """获取数据模型类"""
        return ComplianceAnalysisResult

    def analyze_data(self, filters: ComplianceAnalysisFilters) -> AnalysisResult:
        """分析规范性数据"""
        try:
            # 构建查询
            query = self.build_base_query(filters)

            # 应用特殊筛选
            if filters.compliance_status:
                query = self._apply_compliance_status_filter(query, filters.compliance_status)

            if filters.compliance_type:
                query = self._apply_compliance_type_filter(query, filters.compliance_type)

            if filters.min_confidence is not None:
                query = self._apply_confidence_filter(query, filters.min_confidence)

            if filters.issue_category:
                query = self._apply_issue_category_filter(query, filters.issue_category)

            # 获取基础统计
            basic_stats = self.get_basic_statistics(filters)

            # 获取合规性分布
            compliance_distribution = self.get_compliance_distribution(query, filters)

            # 获取规范性类型分析
            compliance_type_analysis = self.get_compliance_type_analysis(query, filters)

            # 获取问题类别分析
            issue_category_analysis = self.get_issue_category_analysis(query, filters)

            # 获取置信度分析
            confidence_analysis = self.get_confidence_analysis(query, filters)

            # 获取时间序列
            time_series = self.get_time_series_data(filters, 'day')

            # 获取规范性详情
            compliance_details = self.get_compliance_details(query, filters)

            # 组装结果
            result_data = {
                "basic_statistics": basic_stats,
                "compliance_distribution": compliance_distribution,
                "compliance_type_analysis": compliance_type_analysis,
                "issue_category_analysis": issue_category_analysis,
                "confidence_analysis": confidence_analysis,
                "time_series": time_series,
                "compliance_details": compliance_details,
                "analysis_metadata": {
                    "total_records": query.count(),
                    "compliance_rate": compliance_distribution.get('compliance_rate', 0),
                    "average_confidence": confidence_analysis.get('average_confidence', 0),
                    "analysis_time": datetime.now().isoformat()
                }
            }

            return AnalysisResult(
                success=True,
                data=result_data,
                message="规范性分析完成"
            )

        except Exception as e:
            logger.error(f"规范性分析失败: {str(e)}")
            return AnalysisResult(
                success=False,
                data=None,
                message=f"规范性分析失败: {str(e)}"
            )

    def get_compliance_distribution(self, query, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取合规性分布统计"""
        # 按合规状态统计
        results = query.with_entities(
            ComplianceAnalysisResult.gfx_zt.label('compliance_status'),
            func.count().label('count')
        ).filter(
            ComplianceAnalysisResult.gfx_zt.isnot(None),
            ComplianceAnalysisResult.gfx_zt != ''
        ).group_by(
            ComplianceAnalysisResult.gfx_zt
        ).order_by(desc('count')).all()

        status_counts = {}
        for result in results:
            if result.compliance_status:
                status_counts[result.compliance_status] = result.count

        total_count = sum(status_counts.values())
        compliance_count = status_counts.get('compliant', 0)
        compliance_rate = round((compliance_count / total_count) * 100, 2) if total_count > 0 else 0

        return {
            "status_distribution": status_counts,
            "total_count": total_count,
            "compliant_count": compliance_count,
            "non_compliant_count": status_counts.get('non_compliant', 0),
            "partial_count": status_counts.get('partial', 0),
            "compliance_rate": compliance_rate,
            "status_percentages": {
                status: round((count / total_count) * 100, 2) if total_count > 0 else 0
                for status, count in status_counts.items()
            }
        }

    def get_compliance_type_analysis(self, query, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取规范性类型分析"""
        # 按规范性类型统计
        results = query.with_entities(
            ComplianceAnalysisResultgfx_gflx.label('compliance_type'),
            ComplianceAnalysisResult.gfx_zt.label('compliance_status'),
            func.count().label('count')
        ).filter(
            ComplianceAnalysisResult.gfx_gflx.isnot(None),
            ComplianceAnalysisResult.gfx_gflx != ''
        ).group_by(
            ComplianceAnalysisResult.gfx_gflx,
            ComplianceAnalysisResult.gfx_zt
        ).order_by(desc('count')).all()

        # 构建类型分析数据
        type_analysis = {}
        for result in results:
            compliance_type = result.compliance_type
            if compliance_type not in type_analysis:
                type_analysis[compliance_type] = {
                    "total_count": 0,
                    "status_breakdown": {},
                    "compliance_rate": 0
                }

            type_analysis[compliance_type]["total_count"] += result.count
            type_analysis[compliance_type]["status_breakdown"][result.compliance_status] = result.count

        # 计算每个类型的合规率
        for compliance_type, data in type_analysis.items():
            total = data["total_count"]
            compliant_count = data["status_breakdown"].get('compliant', 0)
            data["compliance_rate"] = round((compliant_count / total) * 100, 2) if total > 0 else 0

        return {
            "type_analysis": type_analysis,
            "type_summary": self._summarize_type_analysis(type_analysis)
        }

    def get_issue_category_analysis(self, query, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取问题类别分析"""
        # 按问题类别统计
        results = query.with_entities(
            ComplianceAnalysisResult.gfx_wtlb.label('issue_category'),
            ComplianceAnalysisResult.gfx_zt.label('compliance_status'),
            func.count().label('count')
        ).filter(
            ComplianceAnalysisResult.gfx_wtlb.isnot(None),
            ComplianceAnalysisResult.gfx_wtlb != ''
        ).group_by(
            ComplianceAnalysisResult.gfx_wtlb,
            ComplianceAnalysisResult.gfx_zt
        ).order_by(desc('count')).all()

        # 构建问题类别分析数据
        category_analysis = {}
        for result in results:
            category = result.issue_category
            if category not in category_analysis:
                category_analysis[category] = {
                    "total_count": 0,
                    "status_breakdown": {},
                    "severity_score": 0
                }

            category_analysis[category]["total_count"] += result.count
            category_analysis[category]["status_breakdown"][result.compliance_status] = result.count

        # 计算严重程度分数
        for category, data in category_analysis.items():
            total = data["total_count"]
            non_compliant = data["status_breakdown"].get('non_compliant', 0)
            data["severity_score"] = round((non_compliant / total) * 100, 2) if total > 0 else 0

        # 按严重程度排序
        sorted_categories = sorted(category_analysis.items(), key=lambda x: x[1]["severity_score"], reverse=True)

        return {
            "category_analysis": dict(sorted_categories),
            "top_issues": [category for category, _ in sorted_categories[:5]],
            "severity_distribution": self._calculate_severity_distribution(category_analysis)
        }

    def get_confidence_analysis(self, query, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取置信度分析"""
        confidence_scores = []

        for result in query.all():
            try:
                confidence = result.get_confidence_score()
                confidence_scores.append(confidence)
            except Exception:
                continue

        if not confidence_scores:
            return {
                "average_confidence": 0,
                "min_confidence": 0,
                "max_confidence": 0,
                "distribution": {}
            }

        # 计算统计指标
        avg_confidence = sum(confidence_scores) / len(confidence_scores)
        min_confidence = min(confidence_scores)
        max_confidence = max(confidence_scores)

        # 置信度分布
        distribution = {
            "高置信度 (0.8-1.0)": 0,
            "中置信度 (0.6-0.8)": 0,
            "低置信度 (0.4-0.6)": 0,
            "很低置信度 (0-0.4)": 0
        }

        for score in confidence_scores:
            if score >= 0.8:
                distribution["高置信度 (0.8-1.0)"] += 1
            elif score >= 0.6:
                distribution["中置信度 (0.6-0.8)"] += 1
            elif score >= 0.4:
                distribution["低置信度 (0.4-0.6)"] += 1
            else:
                distribution["很低置信度 (0-0.4)"] += 1

        # 转换为百分比
        total = len(confidence_scores)
        distribution_percentage = {
            k: round((v / total) * 100, 2) for k, v in distribution.items()
        }

        return {
            "average_confidence": round(avg_confidence, 3),
            "min_confidence": round(min_confidence, 3),
            "max_confidence": round(max_confidence, 3),
            "distribution": distribution,
            "distribution_percentage": distribution_percentage,
            "total_samples": total
        }

    def get_compliance_details(self, query, filters: ComplianceAnalysisFilters, limit: int = 10) -> List[Dict[str, Any]]:
        """获取规范性详情"""
        # 获取最新的规范性记录
        results = query.order_by(desc(ComplianceAnalysisResult.created_at)).limit(limit).all()

        compliance_details = []
        for result in results:
            try:
                confidence = result.get_confidence_score()
                compliance_details.append({
                    "id": result.petition_record_id,
                    "compliance_status": result.gfx_zt,
                    "compliance_type": result.gfx_gflx or "未分类",
                    "issue_category": result.gfx_wtlb or "无问题",
                    "reason": result.gfx_yy or "",
                    "suggestion": result.gfx_jy or "",
                    "confidence": round(confidence, 3),
                    "created_at": result.created_at.isoformat()
                })
            except Exception:
                continue

        return compliance_details

    def _apply_compliance_status_filter(self, query, compliance_status: str):
        """应用合规状态筛选"""
        return query.filter(ComplianceAnalysisResult.gfx_zt == compliance_status)

    def _apply_compliance_type_filter(self, query, compliance_type: str):
        """应用规范性类型筛选"""
        return query.filter(ComplianceAnalysisResult.gfx_gflx == compliance_type)

    def _apply_confidence_filter(self, query, min_confidence: float):
        """应用置信度筛选"""
        # 需要根据实际的置信度字段进行调整
        return query  # 简化实现

    def _apply_issue_category_filter(self, query, issue_category: str):
        """应用问题类别筛选"""
        return query.filter(ComplianceAnalysisResult.gfx_wtlb == issue_category)

    def _summarize_type_analysis(self, type_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """总结类型分析"""
        if not type_analysis:
            return {"total_types": 0, "best_performing": None, "worst_performing": None}

        # 按合规率排序
        sorted_types = sorted(type_analysis.items(), key=lambda x: x[1]["compliance_rate"], reverse=True)

        return {
            "total_types": len(type_analysis),
            "best_performing": sorted_types[0] if sorted_types else None,
            "worst_performing": sorted_types[-1] if sorted_types else None,
            "average_compliance_rate": round(sum(data["compliance_rate"] for data in type_analysis.values()) / len(type_analysis), 2)
        }

    def _calculate_severity_distribution(self, category_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """计算严重程度分布"""
        severity_levels = {
            "低风险 (0-20%)": 0,
            "中风险 (20-50%)": 0,
            "高风险 (50-80%)": 0,
            "极高风险 (80-100%)": 0
        }

        for category, data in category_analysis.items():
            severity_score = data["severity_score"]
            if severity_score <= 20:
                severity_levels["低风险 (0-20%)"] += 1
            elif severity_score <= 50:
                severity_levels["中风险 (20-50%)"] += 1
            elif severity_score <= 80:
                severity_levels["高风险 (50-80%)"] += 1
            else:
                severity_levels["极高风险 (80-100%)"] += 1

        return severity_levels

    def get_compliance_trends(self, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取规范性趋势分析"""
        query = self.build_base_query(filters)

        # 按日期和合规状态统计
        daily_compliance = query.with_entities(
            func.date(ComplianceAnalysisResult.created_at).label('date'),
            ComplianceAnalysisResult.gfx_zt.label('compliance_status'),
            func.count().label('count')
        ).filter(
            ComplianceAnalysisResult.gfx_zt.isnot(None),
            ComplianceAnalysisResult.gfx_zt != ''
        ).group_by(
            func.date(ComplianceAnalysisResult.created_at),
            ComplianceAnalysisResult.gfx_zt
        ).order_by('date').all()

        # 构建趋势数据
        trends = {}
        for result in daily_compliance:
            date_str = result.date.isoformat()
            if date_str not in trends:
                trends[date_str] = {}
            trends[date_str][result.compliance_status] = result.count

        # 计算每日合规率
        daily_rates = []
        for date in sorted(trends.keys()):
            day_data = trends[date_str]
            total = sum(day_data.values())
            compliant = day_data.get('compliant', 0)
            rate = round((compliant / total) * 100, 2) if total > 0 else 0
            daily_rates.append({
                "date": date,
                "compliance_rate": rate,
                "total_count": total
            })

        return {
            "daily_compliance_rates": daily_rates,
            "trend_summary": self._calculate_compliance_trend_summary(daily_rates)
        }

    def _calculate_compliance_trend_summary(self, daily_rates: List[Dict]) -> Dict[str, Any]:
        """计算合规性趋势摘要"""
        if not daily_rates:
            return {"trend": "无数据", "change_rate": 0}

        # 计算最近时期和之前时期的平均合规率
        recent_period = daily_rates[-7:] if len(daily_rates) >= 7 else daily_rates
        earlier_period = daily_rates[-14:-7] if len(daily_rates) >= 14 else daily_rates[:len(daily_rates)//2]

        recent_avg = sum(day["compliance_rate"] for day in recent_period) / len(recent_period)
        earlier_avg = sum(day["compliance_rate"] for day in earlier_period) / len(earlier_period) if earlier_period else recent_avg

        change_rate = recent_avg - earlier_avg

        # 判断趋势
        if change_rate > 5:
            trend = "改善趋势"
        elif change_rate < -5:
            trend = "恶化趋势"
        else:
            trend = "稳定趋势"

        return {
            "trend": trend,
            "current_rate": round(recent_avg, 2),
            "previous_rate": round(earlier_avg, 2),
            "change_rate": round(change_rate, 2)
        }

    def get_compliance_by_region(self, filters: ComplianceAnalysisFilters) -> Dict[str, Any]:
        """获取按区域分组的合规性分析"""
        query = self.build_base_query(filters)

        # 按区域和合规状态统计
        regional_compliance = query.with_entities(
            ComplianceAnalysisResult.dzxx_xzq.label('region'),
            ComplianceAnalysisResult.gfx_zt.label('compliance_status'),
            func.count().label('count')
        ).filter(
            ComplianceAnalysisResult.dzxx_xzq.isnot(None),
            ComplianceAnalysisResult.dzxx_xzq != '',
            ComplianceAnalysisResult.gfx_zt.isnot(None),
            ComplianceAnalysisResult.gfx_zt != ''
        ).group_by(
            ComplianceAnalysisResult.dzxx_xzq,
            ComplianceAnalysisResult.gfx_zt
        ).order_by(desc('count')).all()

        # 构建区域分析数据
        regional_analysis = {}
        for result in regional_compliance:
            region = result.region
            if region not in regional_analysis:
                regional_analysis[region] = {
                    "total_count": 0,
                    "status_breakdown": {},
                    "compliance_rate": 0
                }

            regional_analysis[region]["total_count"] += result.count
            regional_analysis[region]["status_breakdown"][result.compliance_status] = result.count

        # 计算每个区域的合规率
        for region, data in regional_analysis.items():
            total = data["total_count"]
            compliant_count = data["status_breakdown"].get('compliant', 0)
            data["compliance_rate"] = round((compliant_count / total) * 100, 2) if total > 0 else 0

        # 按合规率排序
        sorted_regions = sorted(regional_analysis.items(), key=lambda x: x[1]["compliance_rate"], reverse=True)

        return {
            "regional_analysis": dict(sorted_regions),
            "best_regions": [region for region, _ in sorted_regions[:5]],
            "worst_regions": [region for region, _ in sorted_regions[-5:]],
            "average_regional_compliance": round(sum(data["compliance_rate"] for data in regional_analysis.values()) / len(regional_analysis), 2) if regional_analysis else 0
        }